package com.fzj.charging.device.dao.repository.impl;

import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.C;
import com.fzj.charging.device.dao.repository.StationRedisRepository;
import com.fzj.charging.device.pojo.entity.ChargingStation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;


import java.math.BigDecimal;
import java.util.*;

@Repository("geoAndMapMany")
@Slf4j
public class StationRedisGeoAndMapManyRepositoryImpl implements StationRedisRepository {
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public void saveStationLocation(List<ChargingStation> chargingStationList) {
        HashMap<Integer, Point> stationGeoMap = new HashMap<>();
        if(chargingStationList!=null&&!chargingStationList.isEmpty()){
            for (ChargingStation chargingStation : chargingStationList) {
                BigDecimal stationLng = chargingStation.getStationLng();
                BigDecimal stationLat = chargingStation.getStationLat();
                Point point = new Point(new Double(String.valueOf(stationLng)),new Double(String.valueOf(stationLat)) );
                stationGeoMap.put(chargingStation.getId(),point);

                String bigKey = "station_info_"+chargingStation.getId();
                HashMap<String,Object> smallMap = new HashMap<>();
                smallMap.put("id",chargingStation.getId());
                smallMap.put("stationLng",chargingStation.getStationLng());
                smallMap.put("stationLat",chargingStation.getStationLat());
                log.debug("smallMap===>{}",smallMap);
                HashOperations hashOperations = redisTemplate.opsForHash();
                hashOperations.putAll(bigKey,smallMap);
            }
            BoundGeoOperations boundGeoOperations = redisTemplate.boundGeoOps("station_geo");
            boundGeoOperations.add(stationGeoMap);
        }

    }

    @Override
    public List<ChargingStation> selectStation(Double lng, Double lat, Double distance) {
        log.debug("经度：{}，纬度：{}，半径：{}",lng,lat,distance);
        Circle circle = getCircle(lng, lat, distance);
        GeoResults<RedisGeoCommands.GeoLocation<Integer>> stationGeoResult = redisTemplate.boundGeoOps("station_geo").radius(circle);
        log.debug("stationGeoResult===>{}",stationGeoResult);
        HashOperations<String,String,Object> hashOperations = redisTemplate.opsForHash();

        if(stationGeoResult!=null){
            ArrayList<ChargingStation> stationList = new ArrayList<>();
            for (GeoResult<RedisGeoCommands.GeoLocation<Integer>> geoLocationGeoResult : stationGeoResult) {
                RedisGeoCommands.GeoLocation<Integer> content = geoLocationGeoResult.getContent();
                Integer stationId = content.getName();
                log.debug("stationId===>{}",stationId);
                ChargingStation chargingStation = new ChargingStation();
                Object id = hashOperations.get("station_info_" + stationId, "id");
                Object stationLng = hashOperations.get("station_info_" + stationId, "stationLng");
                Object stationLat = hashOperations.get("station_info_" + stationId, "stationLat");
                chargingStation.setId(Integer.valueOf(id.toString()));
                chargingStation.setStationLng(new BigDecimal(stationLng.toString()));
                chargingStation.setStationLat(new BigDecimal(stationLat.toString()));
                log.debug("经度：{}，纬度：{}，半径：{}，场站信息：{}",lng,lat,distance,chargingStation);
                stationList.add(chargingStation);
            }
            return stationList;
        }else {
            return Collections.emptyList();
        }

    }
    public Circle getCircle(Double lng, Double lat, Double distance){
        Point point = new Point(lng, lat);
        Distance geoDistance = new Distance(distance, Metrics.KILOMETERS);//metrics:指标
        return new Circle(point,geoDistance);
    }
}
